package com.itzdm.common.utils;

import com.itzdm.common.config.MinioConfig;
import io.minio.*;
import io.minio.messages.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;

@Component
@Slf4j
public class MinioUtils {
    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfig minioConfig;


    @PostConstruct
    public void init() {
        try {
            // 确保存储桶存在
            createBucket(minioConfig.getBucketName());

            // 只有当桶名为 talkflow 时才设置生命周期规则
            if ("talkflow".equals(minioConfig.getBucketName())) {
                minioClient.setBucketLifecycle(
                        SetBucketLifecycleArgs.builder()
                                .bucket(minioConfig.getBucketName())
                                .config(new LifecycleConfiguration(
                                        List.of(
                                                new LifecycleRule(
                                                        Status.ENABLED,
                                                        null,
                                                        new Expiration((ResponseDate) null, 1, null),
                                                        new RuleFilter("/"),
                                                        "fileExpirationRule",
                                                        null,
                                                        null,
                                                        null
                                                )
                                        )
                                ))
                                .build()
                );
                log.info("已为 talkflow 存储桶设置生命周期规则");
            }
        } catch (Exception e) {
            log.error("设置存储桶生命周期规则失败", e);
        }
    }

    // 获取文件后缀
    private String getFileExtension(String fileName) {
        int lastDotIndex = fileName.lastIndexOf(".");
        return lastDotIndex > -1 ? fileName.substring(lastDotIndex) : "";
    }

    @SneakyThrows
    public void createBucket(String bucketName) {
        log.debug("检查存储桶是否存在: {}", bucketName);
        boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        if (!exists) {
            log.info("创建存储桶: {}", bucketName);

            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    @SneakyThrows
    public List<Bucket> getAllBuckets() {
        log.debug("获取所有存储桶");
        return minioClient.listBuckets();
    }

    @SneakyThrows
    public String uploadFile(MultipartFile file) {
        log.debug("开始上传文件到 MinIO");
        // 确保存储桶存在
        createBucket(minioConfig.getBucketName());

        // 生成随机文件名 + 原文件后缀
        String originalFilename = file.getOriginalFilename();
        String extension = getFileExtension(originalFilename != null ? originalFilename : "");
        // 获取文件夹分类路径
        String filePath = getFilePath(originalFilename);

        String fileName = filePath + UUID.randomUUID().toString().replace("-", "") + extension;
        log.debug("生成的文件名: {}", fileName);

        // 使用 try-with-resources 确保资源正确关闭
        try (InputStream inputStream = file.getInputStream()) {
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .object(fileName)
                    .stream(inputStream, file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build());
            log.debug("文件上传到 MinIO 完成: {}", fileName);
        }
        String endpoint = minioConfig.getEndpoint();
        String bucketName = minioConfig.getBucketName();
        return endpoint + "/" + bucketName + "/" + fileName;
    }

    // 添加一个判断文件夹的方法,上传不同形式的文件放在不同的文件夹
    private String getFilePath(String fileName) {
        String filePath = "";
        if (fileName.endsWith(".jpg") || fileName.endsWith(".png") || fileName.endsWith(".jpeg")) {
            filePath = "images/";
        } else if (fileName.endsWith(".mp4") || fileName.endsWith(".avi") || fileName.endsWith(".mov")) {
            filePath = "videos/";
        } else if (fileName.endsWith(".mp3")) {
            filePath = "audios/";
        } else {
            filePath = "others/";
        }
        return filePath;
    }

    @SneakyThrows
    public String uploadFile(File file, String fileName) {
        log.debug("开始上传文件到 MinIO: {}", fileName);
        // 确保存储桶存在
        createBucket(minioConfig.getBucketName());

        try (InputStream inputStream = new FileInputStream(file)) {
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .object(fileName)
                    .stream(inputStream, file.length(), -1)
                    .contentType("application/octet-stream")
                    .build());
            log.debug("文件上传到 MinIO 完成: {}", fileName);
        }

        return fileName;
    }

    @SneakyThrows
    public void deleteFile(String fileName) {
        log.debug("从 MinIO 删除文件: {}", fileName);
        // 删除前缀
        if (fileName.startsWith("/")) {
            // 共有endpoint和bucketName
            fileName = fileName.substring(1);
        }
        minioClient.removeObject(RemoveObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(fileName)
                .build());
        log.debug("文件删除完成: {}", fileName);
    }

    @SneakyThrows
    public List<Map<String, String>> listFiles() {
        log.debug("获取文件列表");
        List<Map<String, String>> files = new ArrayList<>();

        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder()
                        .bucket(minioConfig.getBucketName())
                        .build());

        for (Result<Item> result : results) {
            Item item = result.get();
            Map<String, String> file = new HashMap<>();
            file.put("fileName", item.objectName());
            file.put("size", String.valueOf(item.size()));
            file.put("lastModified", item.lastModified().toString());
            files.add(file);
        }

        log.debug("获取到 {} 个文件", files.size());
        return files;
    }

    // 下载minio中的文件
    @SneakyThrows
    public InputStream downloadFile(String fileName) {
        log.debug("从 MinIO 下载文件: {}", fileName);
        // 删除前缀
        if (fileName.startsWith("/")) {
            // 共有endpoint和bucketName
            fileName = fileName.substring(1);
        }
        return minioClient.getObject(GetObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(fileName)
                .build());
    }
} 